#include <QMessageBox>
#include <QTextCodec>
#include <QSslSocket>
#include "serviceprovider.h"

ServiceProvider::ServiceProvider(QObject *parent):
    QObject(parent)
{

}

ServiceProvider::ServiceProvider(ServiceProvider &other)
{
    socket=other.socket;
    manager=other.manager;
    GetUrlStr=other.GetUrlStr;
    ServerUrlStr=other.ServerUrlStr;
    protocol=other.protocol;
    userLogin=other.userLogin;
    userPassword=other.userPassword;
}

ServiceProvider::ServiceProvider(const ServiceProvider &other)
{
    socket=other.socket;
    manager=other.manager;
    GetUrlStr=other.GetUrlStr;
    ServerUrlStr=other.ServerUrlStr;
    protocol=other.protocol;
    userLogin=other.userLogin;
    userPassword=other.userPassword;
}

ServiceProvider::ServiceProvider(QString login, QString password, int parameter, QObject *parent):
QObject(parent),
userParameter(parameter)
{
    GetUrlStr=new QString("your service provider url get request string");
    ServerUrlStr=new QString("your service provider url");
    userLogin = new QString(login);
    userPassword = new QString(password);
}

ServiceProvider::~ServiceProvider()
{
    if(userPassword) delete userPassword;
    if(userLogin) delete userLogin;
    if(ServerUrlStr) delete ServerUrlStr;
    if(GetUrlStr) delete GetUrlStr;
}

QSsl::SslProtocol ServiceProvider::getProtocol()
{
    return protocol;
}

ServiceProvider::Operation ServiceProvider::getOperation()
{
    return m_operation;
}

int ServiceProvider::getUserParameter()
{
    return userParameter;
}

void ServiceProvider::setProtocol(QSsl::SslProtocol proto)
{
    protocol=proto;
}

void ServiceProvider::setPaymentContent(ServiceProvider::PaymentContent *content)
{
    m_paymentContent.amount=new QString(*content->amount);
    m_paymentContent.card=new CreditCardProfile(*content->card);
}

void    ServiceProvider::SecureConnect()
{
    emit StageFinished(0);
    if (!socket) {
        //socket = new MySslSocket((quint16)qrand() % ((51000 + 1) - 50000) + 50000);
        socket =  new QSslSocket;
        //socket->setLocalCertificate("c:\Qt\Qt5.4.0\5.4\Src\qtwebsockets\examples\websockets\sslechoserver\localhost");
        //connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
        //        this, SLOT(socketStateChanged(QAbstractSocket::SocketState)));
        connect(socket, SIGNAL(encrypted()),
                this, SLOT(Encrypted()));
        connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
                this, SLOT(socketError(QAbstractSocket::SocketError)));
        connect(socket, SIGNAL(sslErrors(QList<QSslError>)),
                this, SLOT(SslSocketError(QList<QSslError>)));
        connect(socket, SIGNAL(readyRead()),
                this, SLOT(socketReadyRead()));
    }

    qDebug()<<"SecureConnect started";
    manager=NULL;
    socket->setProtocol(protocol);
    socket->setSocketOption(QAbstractSocket::KeepAliveOption,1);

    qDebug()<<"socket.localPort="<<socket->localPort();
    emit StageStarted(userParameter);
    socket->connectToHostEncrypted(*ServerUrlStr, 443);//"https://my.kyivstar.ua"
}

void ServiceProvider::Encrypted()
{
    emit StageFinished(25);
    qDebug()<<"Encrypted";
    if(!manager)
        manager = new QNetworkAccessManager(this);

    QObject::connect(manager, SIGNAL(finished(QNetworkReply*)),
             this, SLOT(finishedGetRequestSlot(QNetworkReply*)));
    QUrl url(*GetUrlStr);
    QNetworkRequest request;
    QSslConfiguration ssl_config;
    ssl_config.setProtocol(protocol);
    request.setSslConfiguration(ssl_config);
    request.setUrl(url);
    manager->get(request);

}

void ServiceProvider::SslSocketError(QList<QSslError> err_list)
{
    qDebug()<<"SSL Socket Errors";
}

void ServiceProvider::socketError(QAbstractSocket::SocketError)
{
    qDebug()<<"socketError";
    //QString *warn= new QString(socket->errorString());
    emit warning(QString(socket->errorString()));
}

void ServiceProvider::socketReadyRead()
{
    qDebug()<<"ReadyRead";
}

void ServiceProvider::finishedGetRequestSlot(QNetworkReply* reply)
{
    emit StageFinished(50);
    QObject::disconnect(manager, SIGNAL(finished(QNetworkReply*)),
                     this, SLOT(finishedGetRequestSlot(QNetworkReply*)));

   if (reply->error() == QNetworkReply::NoError)
   {
       QByteArray bytes = reply->readAll();  // bytes
       QString replyStr=QString::fromUtf8(bytes);
       qDebug()<<replyStr;

       ParseGetReply(replyStr);
       QUrl url(*PostUrl);
       if((PostUrl)&&(*PostUrl!=""))
       {
           QNetworkRequest request;
           QSslConfiguration ssl_config;
           ssl_config.setProtocol(protocol);
           request.setSslConfiguration(ssl_config);
           request.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
           request.setUrl(url);

           QObject::connect(manager, SIGNAL(finished(QNetworkReply*)),
                    this, SLOT(finishedPostRequestSlot(QNetworkReply*)));
           manager->post(request, QString(*PreparePostRequest()).toUtf8());
       }
   }
   else
   {// Some http error received
       qDebug()<<"Get replyError: " << reply->error();
   }
}

void  ServiceProvider::finishedPostRequestSlot(QNetworkReply* reply)
{
    //current_progress+=10;
    //emit StageFinished(current_progress);
//    QObject::disconnect(manager, SIGNAL(finished(QNetworkReply*)),
//             this, SLOT(finishedPostRequestSlot(QNetworkReply*)));
    qDebug()<<"finishedPostRequestSlot";

    // no error received?
    if (reply->error() == QNetworkReply::NoError)
    {
        QByteArray replyBa=reply->readAll();
        QTextCodec* defaultTextCodec = QTextCodec::codecForHtml(replyBa);
        QTextDecoder *decoder = new QTextDecoder(defaultTextCodec);
        //QString str = decoder->toUnicode(replyBa);
        qDebug()<<QString::fromUtf8(replyBa);

        //if(!ParseError(str))
        if(!ParseError(replyBa))
        {
            QVariant statusCodeV = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
            if((statusCodeV==301)||(statusCodeV==302))
            {
                QVariant redirectionTargetUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
                qDebug()<<"redirectionTargetUrl="<<QString(redirectionTargetUrl.toString());
                QUrl url(redirectionTargetUrl.toString());
                QNetworkRequest request;
                QSslConfiguration ssl_config;
                ssl_config.setProtocol(protocol);
                request.setSslConfiguration(ssl_config);
                request.setUrl(url);
                QObject::connect(manager, SIGNAL(finished(QNetworkReply*)),
                         this, SLOT(finishedPostRequestSlot(QNetworkReply*)));
                manager->get(request);
            }
            else
            {
                qDebug()<<"parsing host answer...";
                //ParsePostReply(str);
                ParsePostReply(replyBa);
                socket->close();
            }
        }

    }
    // Some http error received
    else
    {
        qDebug()<<"Post replyError: "<<reply->error();
        // handle errors here

    }

    // We receive ownership of the reply object
    // and therefore need to handle deletion.
    reply->deleteLater();
}

QString  *ServiceProvider::findValue(QString &text, const QString key_start, const QString key_end)
{
    QString *NewStr;
    int start_index=text.indexOf(key_start);
    if(start_index <0)
    {
        return NewStr=new QString("");
    }
    else
    {
        start_index+=+key_start.length();
        int last_index=text.indexOf(key_end,start_index);
        if(last_index>=start_index)
        {
            NewStr= new QString(text.mid(start_index,last_index-start_index));
            qDebug()<<"newStr="<<*NewStr;
            return NewStr;
        }
        else
            return NewStr=new QString("");
    }

}

QString  *ServiceProvider::findValue(QByteArray &text, const QByteArray key_start, const QByteArray key_end)
{
    QString *NewStr;
    int start_index=text.indexOf(key_start);
    if(start_index <0)
    {
        return NewStr=new QString("");
    }
    else
    {
        start_index+=+key_start.length();
        int last_index=text.indexOf(key_end,start_index);
        if(last_index>=start_index)
        {
            NewStr= new QString(text.mid(start_index,last_index-start_index));
            qDebug()<<"newStr="<<*NewStr;
            return NewStr;
        }
        else
            return NewStr=new QString("");
    }

}

ServiceProvider::PaymentResult   ServiceProvider::StartPayment(CreditCardProfile &card, QString login, QString amount)
{
    qDebug()<<"ServiceProvider Payment";
}

ServiceProvider & ServiceProvider::operator =(ServiceProvider &profile)
{
    socket=profile.socket;
    manager=profile.manager;
    GetUrlStr=profile.GetUrlStr;
    ServerUrlStr=profile.ServerUrlStr;
    protocol=profile.protocol;
    userLogin=profile.userLogin;
    userPassword=profile.userPassword;
}

QString&        ServiceProvider::UserLogin()
{
    return *userLogin;
}

QString &ServiceProvider::UserPassword()
{
    return *userPassword;
}
